/***************************************************************************
 *   Copyleft 2006-2007 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./Point4D.h"
#include "./MathConstants.h"

/**************************************************************
* Constructors                                                *
***************************************************************/
Point4D::Point4D(cFloat fX, cFloat fY, cFloat fZ) {
	mX = fX;
	mY = fY;
	mZ = fZ;
	mW = 1.0f;
}

Point4D::Point4D(cFloat fX, cFloat fY, cFloat fZ, cFloat fW) {
	mX = fX;
	mY = fY;
	mZ = fZ;
	mW = fW;
}

Point4D::Point4D(const Point4D& point) {
	mX = point.mX;
	mY = point.mY;
	mZ = point.mZ;
	mW = point.mW;

}

/**************************************************************
* Operators                                                   *
***************************************************************/
Point4D Point4D::operator*(cInt iB) {
	Point4D temp;

	temp.mX = mX * iB;
	temp.mY = mY * iB;
	temp.mZ = mZ * iB;
	temp.mW = mW * iB;

	return temp;
}

Point4D Point4D::operator*(cFloat fB) {
	Point4D temp;

	temp.mX = mX * fB;
	temp.mY = mY * fB;
	temp.mZ = mZ * fB;
	temp.mW = mW * fB;

	return temp;
}

Point4D Point4D::operator*(const Point4D& b) {
	Point4D temp;

	temp.mX = mY * b.mZ - mZ *b.mY;
	temp.mY = mZ * b.mX - mX * b.mZ;
	temp.mZ = mX * b.mY - mY * b.mX;

	return temp;
}

Point4D Point4D::operator/(cInt iB) {
	Point4D temp;

	temp.mX = mX / iB;
	temp.mY = mY / iB;
	temp.mZ = mZ / iB;
	temp.mW = mW / iB;

	return temp;
}

Point4D Point4D::operator/(cFloat fB) {
	Point4D temp;

	temp.mX = mX / fB;
	temp.mY = mY / fB;
	temp.mZ = mZ / fB;
	temp.mW = mW / fB;

	return temp;
}

Point4D Point4D::operator+(const Point4D& b) {
	Point4D temp;

	temp.mX = mX + b.mX;
	temp.mY = mY + b.mY;
	temp.mZ = mZ + b.mZ;
	temp.mW = mW + b.mW;

	return temp;
}

Point4D Point4D::operator-(const Point4D& b) {
	Point4D temp;

	temp.mX = mX - b.mX;
	temp.mY = mY - b.mY;
	temp.mZ = mZ - b.mZ;
	temp.mW = mW - b.mW;

	return temp;
}

Point4D Point4D::operator-() {
	Point4D temp;

	temp.mX = -mX;
	temp.mY = -mY;
	temp.mZ = -mZ;
	temp.mW = -mW;

	return temp;
}

Point4D& Point4D::operator=(const Point4D& point) {
	if (&point != this) {
		for (cInt i = 0; i < 4; i++) {
			mValues[i] = point.mValues[i];
		}
	}

	return *this;
}


/**************************************************************
* Other helpful functions                                     *
***************************************************************/
cVoid Point4D::Normalize() {
	mX /= mW;
	mY /= mW;
	mZ /= mW;

	mW = 1.0f;
}

cFloat Point4D::Abs() {
	return Sqrt(Sqr(mX) + Sqr(mY) + Sqr(mZ));
}

/*virtual*/ TiXmlElement* Point4D::Serialize(TiXmlElement* parent) {
	TiXmlElement* elem = new TiXmlElement("Point3D");
	parent->LinkEndChild(elem);
	elem->SetDoubleAttribute("x", mX);
	elem->SetDoubleAttribute("y", mY);
	elem->SetDoubleAttribute("z", mZ);

	return elem;
}